//
//  PYLeftPopPanTransition.swift
//  ltsp
//
//  Created by jyvyi_ios on 2022/5/20.
//

import Foundation

fileprivate let screenWidth = UIScreen.main.bounds.size.width

fileprivate let screenHeight = UIScreen.main.bounds.size.height

extension UIView{
    
    /// 添加内部手势。控制关闭转场动画，单独添加向左侧滑关闭可用
    func addLeftPopPanGestureRecognizer(navigationController:UINavigationController,transitionCompleteBlock:EmptyCompleteBlock? = nil){
        
        let pan = UIPanGestureRecognizer.init(target: self, action: #selector(leftPopPanInteractiveTransitionRecognizerAction(_:)))
        self.addLeftPopPanGestureRecognizer(pan, navigationController: navigationController, transitionCompleteBlock: transitionCompleteBlock)
        self.addGestureRecognizer(self.leftProperty.leftPopPanGesture!)
    }
    
    /// 添加外部手势，控制关闭转场动画，防止手势过多使用，需要
    /// - Parameter pan: 外部pan手势
    func  addLeftPopPanGestureRecognizer(_ pan:UIPanGestureRecognizer,navigationController:UINavigationController,transitionCompleteBlock:EmptyCompleteBlock? = nil){
        
        self.leftProperty.leftPopPanGesture = pan
        self.leftProperty.leftPopTransition = PYInteractiveAnimatedTransition.init(panGesture: pan)
        self.leftProperty.leftPopTransition?.transitionCompleteBlock = transitionCompleteBlock
        self.leftProperty.pushViewController = navigationController
    }
    
    /// 关联外部pan手势的响应事件
    /// - Parameter gestureRecognizer: 外部pan手势
    func referLeftPopPanGestureRecognizerAction(_ gestureRecognizer:UIPanGestureRecognizer){
        
        self.leftPopPanInteractiveTransitionRecognizerAction(gestureRecognizer)
    }
    
    /// PanGestureRecognizer手势事件
    /// - Parameter gestureRecognizer: PanGestureRecognizer
    @objc fileprivate func leftPopPanInteractiveTransitionRecognizerAction(_ gestureRecognizer:UIPanGestureRecognizer){

        let translationPoint = gestureRecognizer.translation(in: gestureRecognizer.view)
        if self.leftProperty.startX == 0{
            self.leftProperty.startX = translationPoint.x
        }
        switch gestureRecognizer.state{
        case .possible:
            fallthrough
        case .changed:
            fallthrough
        case .began:
            guard abs(translationPoint.x / translationPoint.y) > 1 else {
                return
            }
            guard self.leftProperty.startX > 0 else { //保证为向左滑动
                return
            }
            self.popViewControllerEvent()
        case .failed:
            fallthrough
        case .cancelled:
            fallthrough
        case .ended:
            self.leftProperty.pushViewController?.delegate = nil
            self.leftProperty.isPoped = false
            self.leftProperty.startX = 0
        @unknown default:
            break
        }
    }
    
    func popViewControllerEvent(){
        guard !self.leftProperty.isPoped else {
            return
        }
        self.leftProperty.isPoped = true
        self.leftProperty.pushViewController?.delegate = self.leftProperty.leftPopTransition
        self.leftProperty.pushViewController?.popViewController(animated: true)
    }
}

fileprivate class ViewProperty{
    
    var leftPopTransition : PYInteractiveAnimatedTransition?
    
    var leftPopPanGesture: UIPanGestureRecognizer?
    
    var pushViewController : UINavigationController?
    
    var isPoped : Bool = false
    
    var startX : CGFloat = 0
}
extension UIView{
    
    fileprivate static var KEY_RIGHTPUSH_PROPERTY = "keyForRightPushProperty"
    
    fileprivate var leftProperty : ViewProperty{
        set{
            objc_setAssociatedObject(self, &UIView.KEY_RIGHTPUSH_PROPERTY, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
        get{
            var _property = objc_getAssociatedObject(self, &UIView.KEY_RIGHTPUSH_PROPERTY) as? ViewProperty
            if _property == nil{
                _property = ViewProperty()
                objc_setAssociatedObject(self, &UIView.KEY_RIGHTPUSH_PROPERTY, _property, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
            }
            return _property!
        }
    }
}
//MARK: 转场动画相关
fileprivate class PYInteractiveAnimatedTransition : NSObject,UINavigationControllerDelegate{
    
    var transitionCompleteBlock : EmptyCompleteBlock?
    
    var panGesture : UIPanGestureRecognizer
    
    init(panGesture:UIPanGestureRecognizer){
        
        self.panGesture = panGesture
        super.init()
    }
    
    lazy var interaction: PYPercentIntractive = {
        
        return PYPercentIntractive.init(panGestureRecofgnizer: self.panGesture)
    }()
    lazy var animation: PYAnimatedTransition = {
        
        return PYAnimatedTransition()
    }()
    
    func navigationController(_ navigationController: UINavigationController, interactionControllerFor animationController: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
        
        return self.interaction
    }
    func navigationController(_ navigationController: UINavigationController, animationControllerFor operation: UINavigationController.Operation, from fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
      
        if operation == .pop{
            self.animation.transitionCompleteBlock = self.transitionCompleteBlock
            return self.animation
        }
        else if operation == .push{
            return nil
        }
        return nil
    }
}
//MARK: 交互动画
fileprivate class PYPercentIntractive : UIPercentDrivenInteractiveTransition{
    
    var panGestureRecofgnizer : UIPanGestureRecognizer
    
    init(panGestureRecofgnizer:UIPanGestureRecognizer){
        
        self.panGestureRecofgnizer = panGestureRecofgnizer
        super.init()
        
        self.panGestureRecofgnizer.addTarget(self, action: #selector(gestureRecognizeDidUpdate(_:)))
    }
    
    @objc func gestureRecognizeDidUpdate(_ gestureRecognizer:UIPanGestureRecognizer){
        
        let translationPoint = gestureRecognizer.translation(in: gestureRecognizer.view)
        var scale = translationPoint.x / screenWidth
        let isLeftPop = scale > 0
        scale = abs(scale)
        scale = scale > 1 ? 1 : scale
        
        switch gestureRecognizer.state{
        case .began:
            break
        case .changed:
            self.update(scale)
        case .ended:
            if scale > 0.3 && isLeftPop{
                self.finish()
            }
            else{
                self.cancel()
            }
        default:
            self.cancel()
        }
    }
    deinit{
        self.panGestureRecofgnizer.removeTarget(self, action: #selector(gestureRecognizeDidUpdate(_:)))
    }
    
    //实现 UIViewControllerInteractiveTransitioning 协议的方法（必须实现）
    //开始交互转场
    override func startInteractiveTransition(_ transitionContext: UIViewControllerContextTransitioning) {
        //相当于走到 Animator 中的代理方法去了，那里实现了具体的动画
        super.startInteractiveTransition(transitionContext)
    }
}
//MARK: 转场动画
fileprivate class PYAnimatedTransition : NSObject,UIViewControllerAnimatedTransitioning{
    
    var transitionCompleteBlock : EmptyCompleteBlock?
    
    func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
        
        return 0.4
    }
    
    func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
        //转场过渡的容器view
        let containerView = transitionContext.containerView
        
        guard  let fromViewController = transitionContext.viewController(forKey: .from),
        let toViewController = transitionContext.viewController(forKey: .to)
        else {
            return
        }
        // fromVC
        let fromView = fromViewController.view!
        fromView.frame = CGRect.init(x: 0, y: 0, width: screenWidth, height: screenHeight)
        
        // toVC
        let toView = toViewController.view!
        toView.frame = CGRect.init(x: 0, y: 0, width: screenWidth, height: screenHeight)
    
        //添加视图
        containerView.addSubview(toView)
        containerView.addSubview(fromView)
        fromView.frame = CGRect.init(x: 0, y: 0, width: screenWidth, height: screenHeight)
        
        //添加动画
        UIView.animate(withDuration: self.transitionDuration(using: transitionContext)) {
            
            fromView.frame = CGRect.init(x: screenWidth, y: 0, width: screenWidth, height: screenHeight)
            
        } completion: { isFinished in
            
            let wasCancelled = transitionContext.transitionWasCancelled
            transitionContext.completeTransition(!wasCancelled)
            if !wasCancelled{
                self.transitionCompleteBlock?()
            }
        }
    }
}
